package agenda;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;


/**
 * Classe representativa de um Evento
 * 
 * @author Emerson Borges - emerson.borges@ccc.ufcg.edu.br
 * @author Rafael Lima    - rafael.ufcg10@gmail.com
 *
 */
public class Evento implements Comparable<Evento>, Serializable   {
	
	private static final long serialVersionUID = 4547653628099645356L;
	private String nomeEvento;
	private GregorianCalendar dataEvento;
	private String horarioEvento;
	private String duracaoEvento;
	private String descricaoEvento;
	private String tipoEvento;	
	private List<Contato> listaDeContatos;
	
	final int DURACAO_MINIMA = 0;
	
	private GregorianCalendar dataAux;
	
	/**
	 * Construtor de um evento
	 * 
 	 * @param nomeEvento - nome do do evento
	 * @param dataEvento - data do evento
	 * @param horarioEvento - hora do evento
	 * @param duracaoEvento - duracao do evento
	 * @param descricaoEvento - descricao do evento
	 * @param tipoEvento - tipo do evento
	 * @throws Exception
	 */
	public Evento(String nomeEvento, GregorianCalendar dataEvento, String horarioEvento, String duracaoEvento, 
		String descricaoEvento, String tipoEvento) throws Exception{
		
		if (nomeEvento.equals(null) || dataEvento.equals(null) || horarioEvento.equals(null) || duracaoEvento.equals(null) ||
				descricaoEvento.equals(null) || tipoEvento.equals(null)) {
			throw new Exception("Nenhum dos campos podem ser nulos.");	
		}
		else if(nomeEvento.equals("") || dataEvento.equals("") || horarioEvento.equals("") || duracaoEvento.equals("") ||
				descricaoEvento.equals("")){
			throw new Exception("Nenhum dos campos (exceto o Tipo do Evento) podem ser vazio.");
		}
		this.nomeEvento = nomeEvento;
		this.dataEvento = dataEvento;
		this.horarioEvento = horarioEvento;
		this.duracaoEvento = duracaoEvento;
		this.descricaoEvento = descricaoEvento;
		this.tipoEvento = tipoEvento;
		
		
	}
	
	/**
	 * Construtor de um evento
	 * 
	 * @param nomeEvento - nome do evento 
	 * @param dataEvento - data do evento
	 * @param horarioEvento - hora do evento
	 * @param duracaoEvento - duracao do evento
	 * @param descricaoEvento - descricao do evento
	 * @param contato - contato 
	 * @throws Exception
	 */
	public Evento(String nomeEvento, GregorianCalendar dataEvento, String horarioEvento, String duracaoEvento, 
			String descricaoEvento, Contato contato)  throws Exception {
		
		this(nomeEvento, dataEvento, horarioEvento, duracaoEvento, descricaoEvento, "");
		listaDeContatos.add(contato);
	}

	/**
	 * Metodo para acessar o nome do evento
	 * 
	 * @return nomeEvento
	 */
	public String getNomeEvento(){

		return nomeEvento;
	}
	
	/**
	 * Metodo para modificar o nome do evento
	 * 
	 * @param nomeEvento
	 */
	public void setNomeEvento(String nomeEvento) throws Exception{
		if((nomeEvento.equals(null)) || (nomeEvento.equals(""))){
			throw new Exception("Informe um nome para o evento.");
		}
		this.nomeEvento = nomeEvento;
	}
	
	/**
	 * Metodo para acessar a data do evento 
	 * 
	 * @return dataEvento
	 */
	public GregorianCalendar getDataEvento(){
		return dataEvento;
	}
	
	/**
	 * Metodo para modificar o a data do evento
	 * 
	 * @param dataEvento
	 */
	public void setDataEvento(GregorianCalendar dataEvento) throws Exception{
		if((dataEvento.equals(null)) || (dataEvento.equals(""))){
			throw new Exception("Informe uma data para o evento");
		}
		
		this.dataEvento = dataEvento;
	}
	
	/**
	 * Metodo para acessar o horario do evento
	 * 
	 * @return horarioInicioEvento
	 */
	public String getHorarioEvento(){
		return horarioEvento;
	}
	
	/**
	 * Metodo para modificar o horario do evento
	 * 
	 * @param horarioEvento
	 */
//	public void setHorarioEvento(GregorianCalendar horarioEvento)  throws Exception {
//		if((horarioEvento.equals(null)) || (horarioEvento.equals(""))){
//			throw new Exception("Informe o horario do inicio do evento.");
//		}
//		dataAux = avaliaDataHoraEvento(dataEvento, horarioEvento);
//		this.horarioEvento = horarioEvento;
//	}
	
	/**
	 * Metodo para acessar a duracao do evento
	 * 
	 * @return duracaoEvento
	 */
	public String getDuracaoEvento(){
		return duracaoEvento;
	}
	
	/**
	 * Metodo para modificar a duracao do evento
	 * 
	 * @param duracaoEvento
	 */
	public void setDuracaoEvento(String duracaoEvento) throws Exception {
		if(((duracaoEvento.equals(null)) || (duracaoEvento.equals("")))){
			throw new Exception("Informe a duracao do evento.");
		}
        avaliaDuracaoEvento(duracaoEvento);
		this.duracaoEvento = duracaoEvento;
	}
	
	/**
	 * Metodo para acessar a data e a hora de um evento
	 * 
	 * @return
	 */
	public Date getDataHoraEvento(){
		return dataAux.getTime();
	}
	
	/**
	 * Metodo para acessar a descricao do evento
	 * 
	 * @return descricaoEvento
	 */
	public String getDescricaoEvento(){
		return descricaoEvento;
	}
	
	/**
	 * Metodo para modificar a descricao do evento
	 * 
	 * @param descricaoEvento
	 */
	public void setDescricaoEvento(String descricaoEvento) throws Exception{
		if((descricaoEvento.equals(null)) || (descricaoEvento.equals(""))){
		throw new Exception("Informe uma descricao para o evento.");
		}
		this.descricaoEvento = descricaoEvento;
	}
	
	/**
	 * Metodo para acessar o tipo do evento
	 * 
	 * @return tipoEvento
	 */
	public String getTipoEvento() {
		return tipoEvento;
	}

	/**
	 * Metodo para modificar o tipo do evento
	 * 
	 * @param tipoEvento
	 */
	public void setTipoEvento(String tipoEvento) {
		this.tipoEvento = tipoEvento;
	}
	
	public List<Contato> getListaDeContatos() {
		return listaDeContatos;
	}
	
	/**
	 * Metodo para fazer a pesquisa de um contato em um evento
	 * 
	 * @param contato
	 * @return String
	 */
	 public String pesquisaContato(Contato contato) {
         for (Contato contatoAux : listaDeContatos) {
                 if (contato.getNome().equals(contatoAux.getNome()) && contatoAux.getAniversario().equals(contatoAux.getAniversario())){
                         return contato.getNome();
                 }
         }
         return "O contato nao esta na lista do evento";
	 }
	 
	/**
	 * Metodo para adicionar contato ao evento
	 * 
	 * @param contato
	 * @return boolean
	 */
	 public void adicionaContato(Contato contato) {
		 listaDeContatos.add(contato);
	 }
	 
	 /**
	  * Metodo para remover um contato do evento
	  * 
	  * @param contato
	  * @return
	  */
	 public boolean removeContato(Contato contato){
		 listaDeContatos.remove(contato);
		return true;
	 }
	 
	 /**
	  * Metodo para avaliar a duracao do evento
	  * 
	  * @param duracaoEvento
	  * @throws Exception
	  */
	 private void avaliaDuracaoEvento(String duracaoEvento) throws Exception{
		 if(Integer.parseInt(duracaoEvento) < DURACAO_MINIMA){
			 throw new Exception("Tempo minimo de um evento deve ser maior que 0 (zero).");
		 }
	 }
	 
	 /**
	  * Metodo para avaliar se dois eventos estao se sobrepondo
	  * 
	  * @param novoEvento
	  * @return boolean
	  */
	 public boolean avaliaChoqueEventos(Evento novoEvento){
		 if(getDataHoraEvento().equals(novoEvento.getDataHoraEvento())){
			 return true;
		 }
		 return false;
	 }
	 
	 /**
	  * Metodo para avaliar a forma que foi passada a data e a hora do evento eh valida ou nao eh valida
	  * 
	  * @param dataEvento2
	  * @param horarioEvento2
	  * @return dataEvento
	  */
//	 private GregorianCalendar avaliaDataHoraEvento(GregorianCalendar dataEvento2, GregorianCalendar horarioEvento2) throws Exception{
//		 if(dataEvento2.split("/").length !=3){
//			 throw new Exception("Formato correto da data: dd/MM/yyyy");
//		 }if(horarioEvento2.split(":").length != 2){
//			 throw new Exception("Formato correto do horario: hh:mm");
//		 }
//		 GregorianCalendar dataDoEvento = new GregorianCalendar(Integer.parseInt(dataEvento2.split("/")[2]),
//				 (Integer.parseInt(dataEvento2.split("/")[1])) - 1, Integer.parseInt(dataEvento2.split("/")[0]),
//				 Integer.parseInt(horarioEvento2.split(":")[0]), Integer.parseInt(horarioEvento2.split(":")[1]));
//         return dataDoEvento;
//	 }
	 
	public int compareTo(Evento evento){
		return getDataHoraEvento().compareTo(evento.getDataHoraEvento());
	}
	
	public String toString(){
		return String.format("Nome: %s\nData: %s\nHorario: %s\nDuracao: %s\nDescricao: %s\nTipo: %s\n",
				getNomeEvento(), new SimpleDateFormat("dd/MM/YYYT HH:mm").format(getDataEvento().getTime()), getHorarioEvento(), getDuracaoEvento(), getDescricaoEvento(), getTipoEvento());
	}
	
	public boolean equals(Object obj){
		if(!(obj instanceof Evento)){
			return false;
		}
		Evento outro = (Evento) obj;
		return getNomeEvento().equals(outro.getNomeEvento()) &&
				getDataEvento().equals(outro.getDataEvento()) &&
				getHorarioEvento().equals(outro.getHorarioEvento())
				&& getDuracaoEvento().equals(outro.getDuracaoEvento())
				&& getDescricaoEvento().equals(outro.getDescricaoEvento());

	}
	
}